package controller

import (
	"context"
	"encoding/json"
	"os"
	"sort"
	"strconv"
	"strings"
	"time"

	"sale-admin/config"
	"sale-admin/config/mysql"
	"sale-admin/config/redis"
	"sale-admin/internal/app/web/schema"
	"sale-admin/internal/app/web/service"
	"sale-admin/internal/app/web/service/common"
	"sale-admin/internal/app/web/service/coupon"
	"sale-admin/internal/app/web/service/lottery"
	"sale-admin/internal/app/web/service/redemption"
	"sale-admin/internal/app/web/service/robot"
	"sale-admin/internal/dao"
	"sale-admin/internal/define"
	"sale-admin/internal/models"

	"192.168.1.75/go-pkg/errorx"
	"192.168.1.75/go-pkg/helper"
	"192.168.1.75/go-pkg/logx"
	"192.168.1.75/go-pkg/response"
	"github.com/gin-gonic/gin"
	"github.com/gin-gonic/gin/binding"
)

type Robot struct{}

// UpGoodsClick 上报商品点击量
func (r Robot) UpGoodsClick(c *gin.Context) {
	var upGoodsClickData robot.UpGoodsClickData
	c.ShouldBindWith(&upGoodsClickData, binding.JSON)
	// json序列化，加入redis队列
	js, _ := json.Marshal(upGoodsClickData)
	ctx, cancel := context.WithTimeout(context.Background(), time.Second*3)
	defer cancel()
	rdb := redis.NewDB()
	listLen, err1 := rdb.LLen(ctx, define.RedisGoodsClickDataList).Result()
	if err1 == nil && listLen < 20000 {
		_, err2 := rdb.LPush(ctx, define.RedisGoodsClickDataList, string(js)).Result()
		if err2 == nil {
			common.JSONOld(c, nil, errorx.New("写入成功", 1))
			return // 加入队列成功直接返回
		}
	} else {
		logx.Error(context.Background(), "Get GoodsClickDataList length error", logx.Int64("length", listLen), logx.Err(err1))
	}
	// 加入队列失败，则直接保存进数据库
	db := mysql.NewDB()
	err := robot.RobotClick{}.UpGoodsClick(c.Request.Context(), db, upGoodsClickData)
	common.JSONOld(c, nil, err)
}

// UpFaceData 上报曝光量
func (r Robot) UpFaceData(c *gin.Context) {
	var params struct {
		SalesID     string `json:"SalesID"`
		RobotName   string `json:"RobotName"`
		StartTime   int64  `json:"StartTime"`
		EndTime     int64  `json:"EndTime"`
		FaceCount   int64  `json:"FaceCount"`
		FaceCount0  int64  `json:"FaceCount0"`
		FaceCount1  int64  `json:"FaceCount1"`
		FaceCount2  int64  `json:"FaceCount2"`
		FaceCount3  int64  `json:"FaceCount3"`
		StareCount  int64  `json:"StareCount"`
		StareCount0 int64  `json:"StareCount0"`
		StareCount1 int64  `json:"StareCount1"`
		StareCount2 int64  `json:"StareCount2"`
		StareCount3 int64  `json:"StareCount3"`
		AgeGender   []struct {
			Age    int64 `json:"Age"`
			Male   int64 `json:"Male"`
			Female int64 `json:"Female"`
		} `json:"AgeGender"`
	}
	err := c.ShouldBindBodyWith(&params, binding.JSON)
	if err != nil {
		common.JSONOld(c, nil, errorx.New("参数错误", -1))
		return
	}

	db := mysql.NewDB()
	err = robot.FaceCount{}.UpFaceData(c.Request.Context(), db, params.SalesID, params.RobotName,
		params.StartTime, params.EndTime, params.FaceCount, params.FaceCount0, params.FaceCount1, params.FaceCount2, params.FaceCount3,
		params.StareCount, params.StareCount0, params.StareCount1, params.StareCount2, params.StareCount3, params.AgeGender)
	common.JSONOld(c, nil, err)
}

// 机器性别年龄信息上报
func (r Robot) UpPhysicalInfo(c *gin.Context) {
	var params struct {
		Age     int    `json:"Age"`
		Sex     int    `json:"Sex"`
		Type    int    `json:"Type"`
		Msg     string `json:"Msg"`
		SalesID string `json:"SalesID"`
	}
	err := c.ShouldBindJSON(&params)
	if err != nil {
		common.JSONOld(c, nil, errorx.New("参数错误", -1))
		return
	}

	db := mysql.NewDB()
	err = robot.RobotService{}.UpPhysicalInfo(c.Request.Context(), db, params.Age, params.Sex, params.Type, params.Msg, params.SalesID)
	common.JSONOld(c, nil, err)
}

// Login 97平板机器登录
func (r Robot) Login(c *gin.Context) {
	var params struct {
		SalesID   string `json:"SalesID"`   // sales_id
		RobotName string `json:"RobotName"` // robot_name
	}
	c.ShouldBindBodyWith(&params, binding.JSON)

	db := mysql.NewDB()

	// 机器登录
	data, err := robot.RobotService{}.Login(c.Request.Context(), db, params.SalesID, params.RobotName)
	logx.Info(c.Request.Context(), "Robot Login", logx.String("SalesID", params.SalesID),
		logx.String("RobotName", params.RobotName), logx.Any("data", data), logx.Any("err", err))

	data1, _ := common.Marshal(data)
	data2 := make(map[string]interface{})
	json.Unmarshal(data1, &data2)
	common.JSONOld(c, map[string]interface{}{
		"Data": []map[string]interface{}{data2},
	}, err)
}

// 【后台】获取商品信息，不需要传only_sort，这个是安卓使用的。
func (r Robot) GoodsInfo(c *gin.Context) {
	var params struct {
		SalesID    string `json:"sales_id"`
		GetDetails int    `json:"get_details"`
	}
	err := c.ShouldBindBodyWith(&params, binding.JSON)
	if err != nil {
		response.JSON(c, nil, errorx.New("参数错误", -1))
		return
	}

	db := mysql.NewDB()
	data, err := robot.RobotGoods{}.GoodsInfo(c.Request.Context(), db, params.SalesID, params.GetDetails, "", "")
	response.JSON(c, data, err)
}

// 【安卓】 获取商品信息
func (r Robot) RobotGoodsInfo(c *gin.Context) {
	var params struct {
		SalesID    string `json:"SalesID"`
		GetDetails int    `json:"GetDetails"`
		OnlySort   string `json:"OnlySort"`
	}
	if c.ShouldBindBodyWith(&params, binding.JSON) != nil {
		common.JSONOld(c, nil, errorx.New("参数错误", -1))
		return
	}
	db := mysql.NewDB()
	GetDetails := params.GetDetails

	// 获取数据
	data, _ := robot.RobotGoods{}.GoodsInfo(c.Request.Context(), db, params.SalesID, GetDetails, params.OnlySort, "1")
	// 输出数据
	MyResult := robot.GoodsInfoResultOld{}
	MyResult.Remark = data.Remark
	MyResult.Phone = data.Phone
	for _, v := range data.Data { // 用于安卓的补货
		var item robot.ResultGoodsInfoOld // 兼容旧的安卓返回数据类型
		item.GoodsID, _ = strconv.Atoi(v.GoodsID)
		item.ClassID, _ = strconv.Atoi(v.ClassID)
		item.GoodsCode, _ = strconv.Atoi(v.GoodsCode)

		item.SalesID = v.SalesID
		item.GoodsInventory = v.GoodsInventory
		item.GoodsMaxInventory = v.GoodsMaxInventory
		item.ContainerFloor = v.ContainerFloor
		item.ContainerNum = v.ContainerNum
		item.AddTime = v.AddTime
		item.GoodsStatus = v.GoodsStatus
		item.ContainerType = v.ContainerType
		item.Sort = v.Sort
		item.ContainerStatus = v.ContainerStatus
		item.ContainerUseStatus = v.ContainerUseStatus
		item.CreatedAt = v.CreatedAt
		item.Price = v.Price
		item.GoodsName1 = v.GoodsName1
		// item.GoodsDescription1 = v.GoodsDescription1
		item.GoodsImage = v.GoodsImage
		item.TotalSales = v.TotalSales
		item.UseRC = v.UseRC
		if v.GoodsName2 == "" {
			item.GoodsName2 = v.GoodsName1
		} else {
			item.GoodsName2 = v.GoodsName2
		}
		// item.GoodsDescription2 = v.GoodsDescription2
		if v.GoodsName3 == "" {
			item.GoodsName3 = v.GoodsName1
		} else {
			item.GoodsName3 = v.GoodsName3
		}
		// item.GoodsDescription3 = v.GoodsDescription3
		item.CodeImage = v.CodeImage
		item.IsAuth = v.IsAuth
		if v.Price1 > 0 {
			item.Price1 = v.Price1
		}
		// if v.VoiceKeywords != "" {
		// 	myVoiceKeywords := strings.ReplaceAll(v.VoiceKeywords, "，", ",")
		// 	item.VoiceKeywords = strings.Split(myVoiceKeywords, ",")
		// }
		item.GoodsDetail = v.GoodsDetail
		item.GoodsVoice = v.GoodsVoice
		item.ShowTag = v.ShowTag
		item.GoodsType = v.GoodsType
		item.Spring = v.Spring
		item.Container = v.Container
		item.Points = v.Points
		item.PointsSupport = v.PointsSupport
		item.TagCode = v.TagCode
		item.PurchaseType = v.PurchaseType
		MyResult.Data = append(MyResult.Data, item)
	}
	// 只有DataSort显示多规格商品信息
	for _, v := range data.DataSort { // 用于安卓的商品列表显示
		var item robot.ResultGoodsInfoOld // 兼容旧的安卓返回数据类型
		item.GoodsID, _ = strconv.Atoi(v.GoodsID)
		item.ClassID, _ = strconv.Atoi(v.ClassID)
		item.GoodsCode, _ = strconv.Atoi(v.GoodsCode)
		item.SalesID = v.SalesID
		item.GoodsInventory = v.GoodsInventory - v.GoodsReserveInventory
		item.GoodsMaxInventory = v.GoodsMaxInventory
		item.ContainerFloor = v.ContainerFloor
		item.ContainerNum = v.ContainerNum
		item.AddTime = v.AddTime
		item.GoodsStatus = v.GoodsStatus
		item.ContainerType = v.ContainerType
		item.Sort = v.Sort
		item.ContainerStatus = v.ContainerStatus
		item.ContainerUseStatus = v.ContainerUseStatus
		item.CreatedAt = v.CreatedAt
		item.Price = v.Price
		item.GoodsName1 = v.GoodsName1
		item.GoodsDescription1 = v.GoodsDescription1
		item.GoodsImage = v.GoodsImage
		item.TotalSales = v.TotalSales
		item.UseRC = v.UseRC
		if v.GoodsName2 == "" {
			item.GoodsName2 = v.GoodsName1
		} else {
			item.GoodsName2 = v.GoodsName2
		}
		item.GoodsDescription2 = v.GoodsDescription2
		if v.GoodsName3 == "" {
			item.GoodsName3 = v.GoodsName1
		} else {
			item.GoodsName3 = v.GoodsName3
		}
		item.GoodsDescription3 = v.GoodsDescription3
		item.CodeImage = v.CodeImage
		item.IsAuth = v.IsAuth
		if v.Price1 > 0 {
			item.Price1 = v.Price1
		}
		item.GoodsDetail = v.GoodsDetail
		item.GoodsVoice = v.GoodsVoice
		item.ShowTag = v.ShowTag
		item.GoodsType = v.GoodsType
		item.Spring = v.Spring
		item.Container = v.Container
		item.Points = v.Points
		item.PointsSupport = v.PointsSupport
		if v.VoiceKeywords != "" {
			myVoiceKeywords := strings.ReplaceAll(v.VoiceKeywords, "，", ",")
			item.VoiceKeywords = strings.Split(myVoiceKeywords, ",")
		}
		item.RecommendImage = v.RecommendImage
		item.Recommend = v.Recommend
		item.AdImage = v.AdImage
		item.CornerLabelImage = v.CornerLabelImage
		item.TagCode = v.TagCode
		item.PurchaseType = v.PurchaseType

		// 多规格商品信息
		item.Multi = v.Multi
		item.MultiGroupID, _ = strconv.Atoi(v.MultiGroupID)
		item.MultiGroupName = v.MultiGroupName
		item.MultiGroupDetail = v.MultiGroupDetail
		item.MultiSort = v.MultiSort
		item.MultiGroupImage = []string{}
		if len(v.MultiGroupImage) > 0 {
			item.MultiGroupImage = v.MultiGroupImage
		}

		// 活动商品信息
		item.Activity = v.Activity
		item.ActivityList = []robot.MultiDiscountGoodsInfo{}
		if len(v.ActivityList) > 0 {
			item.ActivityList = v.ActivityList
		}

		MyResult.DataSort = append(MyResult.DataSort, item)
	}

	sort.Slice(MyResult.DataSort, func(i, j int) bool {
		return MyResult.DataSort[i].Sort < MyResult.DataSort[j].Sort
	})

	data1, _ := common.Marshal(MyResult)
	data2 := make(map[string]interface{})
	err := json.Unmarshal(data1, &data2)
	common.JSONOld(c, data2, err)
}

// 获取机器详情 --- 默认机器没有配置支付方式
func (r Robot) GetDetailOfRobot(c *gin.Context) {
	var Params struct {
		SalesID string `json:"sales_id"`
	}

	err := c.ShouldBindBodyWith(&Params, binding.JSON)
	if err != nil {
		response.JSON(c, nil, errorx.New("参数错误!", -1))
		return
	}
	merchantID := c.GetString("merchant_id")
	db := mysql.NewDB()
	RobotInfo, _ := robot.RobotService{}.CheckRobotExist(c.Request.Context(), db, Params.SalesID, "")

	// 获取当前商户所拥有的支付方式
	merchantInfo, merchantCount, _ := dao.MerchantConfig{}.GetDetail(c.Request.Context(), db, merchantID)
	// 如果配置不存在，则新增商户配置
	if merchantCount == 0 {
		response.JSON(c, nil, errorx.New("参数配置失败，请重新获取!", -1))
		return
	}

	// if RobotInfo.PaymentType1 == "" || RobotInfo.PaymentType1 == "0" || RobotInfo.PaymentType2 == "" || RobotInfo.PaymentType2 == "0" || RobotInfo.PaymentType3 == "" || RobotInfo.PaymentType3 == "0" || RobotInfo.PaymentType4 == "" || RobotInfo.PaymentType4 == "0" {

	// 初始化的操作。默认填充。
	if (RobotInfo.PaymentType1 == "" || RobotInfo.PaymentType1 == "0") && (RobotInfo.PaymentType2 == "" || RobotInfo.PaymentType2 == "0") && (RobotInfo.PaymentType3 == "" || RobotInfo.PaymentType3 == "0") && (RobotInfo.PaymentType4 == "" || RobotInfo.PaymentType4 == "0") {
		// 当前商户所拥有的支付方式
		myPaymentID := strings.Split(merchantInfo.PaymentsID, ",")
		var pay1 string
		var pay2 string
		var pay3 string
		var pay4 string
		if len(myPaymentID) != 0 {
			if len(myPaymentID) >= 1 {
				pay1 = myPaymentID[0]
			} else {
				pay1 = ""
			}
			if len(myPaymentID) >= 2 {
				pay2 = myPaymentID[1]
			} else {
				pay2 = ""
			}
			if len(myPaymentID) >= 3 {
				pay3 = myPaymentID[2]
			} else {
				pay3 = ""
			}
			if len(myPaymentID) >= 4 {
				pay4 = myPaymentID[3]
			} else {
				pay4 = ""
			}
		}
		RobotInfo.PaymentType1 = pay1
		RobotInfo.PaymentType2 = pay2
		RobotInfo.PaymentType3 = pay3
		RobotInfo.PaymentType4 = pay4
	} else {
		// 1 获取当前机器默认的支付方式,并赋值给当前的机器
		Default := service.RobotPayment{}.GetRobotDefaultPayments(context.Background(), db, RobotInfo.SalesID, merchantID, 0)
		// 2 获取机器已经配置的信息。
		Config, _ := service.RobotPayment{}.GetRobotConfiguredPayments(context.Background(), db, RobotInfo.SalesID, 0, RobotInfo)
		// 取差集 【default】 > 【config】
		// 3.循环已经默认的机器支付方式 , 获取机器没有配置，但需要配置的支付方式
		if len(Config) > 0 {
			for k := range Default {
				if _, ok := Config[k]; !ok {
					if RobotInfo.PaymentType1 == "" || RobotInfo.PaymentType1 == "0" {
						RobotInfo.PaymentType1 = k
						continue
					}
					if RobotInfo.PaymentType2 == "" || RobotInfo.PaymentType2 == "0" {
						RobotInfo.PaymentType2 = k
						continue
					}
					if RobotInfo.PaymentType3 == "" || RobotInfo.PaymentType3 == "0" {
						RobotInfo.PaymentType3 = k
						continue
					}
					if RobotInfo.PaymentType4 == "" || RobotInfo.PaymentType4 == "0" {
						RobotInfo.PaymentType4 = k
						continue
					}
				}
			}
		}
	}

	response.JSON(c, RobotInfo, nil)
}

// SetOpening 设置机器新城新店标识
func (r Robot) SetOpening(c *gin.Context) {
	var params struct {
		RobotID     string `json:"robot_id"`
		OpeningFlag string `json:"opening_flag"`
		OpeningTime string `json:"opening_time"`
	}
	err := c.ShouldBindBodyWith(&params, binding.JSON)
	if err != nil {
		response.JSON(c, nil, errorx.New("参数错误", -1))
		return
	}
	err = robot.RobotService{}.SetOpening(c.GetString("merchant_id"), params.RobotID, params.OpeningFlag, params.OpeningTime)
	response.JSON(c, nil, err)
}

// GetOpening 获取新城新店设置
func (r Robot) GetOpening(c *gin.Context) {
	openingFlag, openingTime := robot.RobotService{}.GetOpening(c.Query("robot_id"))
	response.JSON(c, map[string]interface{}{
		"opening_flag": openingFlag,
		"opening_time": openingTime,
	}, nil)
}

// SetPayment 设置机器支付方式
func (r Robot) SetPayment(c *gin.Context) {
	var Params schema.RobotPaymentConfig

	err := c.ShouldBindBodyWith(&Params, binding.JSON)
	if err != nil {
		response.JSON(c, nil, errorx.New("参数错误!", -1))
		return
	}
	MerchantID := c.GetString("merchant_id")

	db := mysql.NewDB()

	// 设置机器支付方式
	count, err := service.RobotPayment{}.SetRobotPayments(
		c.Request.Context(),
		db,
		MerchantID,
		Params,
	)
	if err == nil && count >= 0 {
		response.JSON(c, count, errorx.New("配置成功！", 0))
	} else {
		logx.Error(context.Background(), "SetPayment err", logx.Any("err", err))
		response.JSON(c, count, errorx.New("配置失败", -1))
	}
}

// [安卓] SetGoods 补货设置
func (r Robot) AndriodSetGoods(c *gin.Context) {
	var params schema.AndriodRobotSalesInfoParams // 安卓传输的是大写。结构体需要兼容
	err := c.ShouldBindJSON(&params)
	if err != nil {
		response.JSON(c, nil, errorx.New("参数错误", -1))
		return
	}
	if len(params.Data) == 0 {
		response.JSON(c, 0, errorx.New("设置商品信息不能为空", 1009))
	}
	for key, val := range params.Data {
		if val.ContainerType == nil {
			a := "-1"
			val.ContainerType = &a
		}
		if val.ContainerUseStatus == nil {
			a := "-1"
			val.ContainerType = &a // 巨坑勿动
		}
		params.Data[key] = val
	}
	// 获取当前账号的商户ID
	MerchantID := c.GetString("merchant_id")

	// 开启补货锁
	db := mysql.NewDB()
	rdx := redis.NewDB()
	success, _ := rdx.SetNX(c.Request.Context(), define.RedisSetGoodsLock+params.SalesID, 1, 3*time.Second).Result()
	if !success {
		common.JSONOld(c, nil, errorx.New("操作过于频繁", -1))
		return
	}
	count, data, err := robot.RobotService{}.AndriodSetGoods(c.Request.Context(), db, MerchantID, params, params.UserID)

	// 转换大小写
	data1, _ := common.Marshal(data)
	data2 := make(map[string]interface{})
	json.Unmarshal(data1, &data2)

	if err == nil && count > 0 {
		common.JSONOld(c, data2, errorx.New("补货成功！", 1))
	} else {
		common.JSONOld(c, data2, errorx.New("补货失败！", -1))
	}
}

// [后台] 设置补货
func (r Robot) SetGoods(c *gin.Context) {
	var params schema.RobotSalesInfoParams
	c.ShouldBindJSON(&params)
	if len(params.Data) == 0 {
		response.JSON(c, 0, errorx.New("设置商品信息不能为空", 1009))
	}
	for key, val := range params.Data {
		if val.ContainerType == nil {
			*val.ContainerType = -1
		}
		if val.ContainerUseStatus == nil {
			*val.ContainerUseStatus = -1
		}
		params.Data[key] = val
	}
	// 获取当前账号的商户ID
	MerchantID := c.GetString("merchant_id")
	// 实例化MySql db
	db := mysql.NewDB()
	rdx := redis.NewDB()
	success, _ := rdx.SetNX(c.Request.Context(), define.RedisSetGoodsLock+params.SalesID, 1, 3*time.Second).Result()
	if !success {
		response.JSON(c, nil, errorx.New("操作过于频繁", -1))
		return
	}

	// 设置机器商品
	count, data, err := robot.RobotService{}.SetGoods(c.Request.Context(), db, MerchantID, params, c.GetString("user_id"))
	if err == nil && count > 0 {
		response.JSON(c, data, errorx.New("补货成功！", 0))
	} else {
		logx.Error(context.Background(), "补货失败", logx.Err(err))
		response.JSON(c, data, errorx.New("补货失败！", -1))
	}
}

// 上报出货时间
func (r Robot) UpdateToOrderTimes(c *gin.Context) {
	var params struct {
		SalesID    string `json:"sales_id"`
		OutTradeNo string `json:"out_trade_no"`
		Times      struct {
			Time1  int `json:"time1"`
			Time2  int `json:"time2"`
			Time3  int `json:"time3"`
			Time4  int `json:"time4"`
			Time5  int `json:"time5"`
			Time6  int `json:"time6"`
			Time7  int `json:"time7"`
			Time8  int `json:"time8"`
			Time9  int `json:"time9"`
			Time10 int `json:"time10"`
		} `json:"times"`
	}
	err := c.ShouldBindBodyWith(&params, binding.JSON)
	if err != nil {
		response.JSON(c, nil, errorx.New("参数错误", -1))
		return
	}

	merchantID := c.GetString("merchant_id")
	db := mysql.NewDB()
	err = robot.RobotService{}.UpdateToOrderTimes(c.Request.Context(), db, merchantID, params.SalesID, params.OutTradeNo, params.Times)
	response.JSON(c, nil, err)
}

// CreateOrderPluralGoods 机器创建订单
func (r Robot) CreateOrderPluralGoods(c *gin.Context) {
	var params struct {
		PaymentAmount     float64                      `json:"PaymentAmount"`     // payment_amount
		CouponCode        string                       `json:"CouponCode"`        // 【选填】优惠码 coupon_code
		SalesID           string                       `json:"SalesID"`           // sales_id
		Data              []schema.OrderGoodsDetailOld `json:"Data"`              // data
		OrigialOutTradeNo string                       `json:"OrigialOutTradeNo"` // origial_out_trade_no 原始订单号
		Type              int                          `json:"Type"`              // type 0 7 9 定义是否兼容了赠送 多件商品购买
		PaymentType       int                          `json:"PaymentType"`       // type 1,2,3,4,5,6,7,8,9
	}
	err := c.ShouldBindBodyWith(&params, binding.JSON)
	if err != nil {
		common.JSONOld(c, nil, errorx.New("参数错误", -1))
		return
	}

	db := mysql.NewDB()
	oldDataBytes, _ := json.Marshal(params.Data)
	NewData := common.Order{}.CountDataOldToNew(string(oldDataBytes))
	data, err := robot.RobotService{}.CreateOrder(c.Request.Context(), db, c.RemoteIP(),
		params.SalesID, params.PaymentAmount, NewData, params.Type,
		params.PaymentType, // 【选填，指定支付方式 默认0】
		"",
		params.OrigialOutTradeNo, // 【选填，原始订单号】
		params.CouponCode,        // 【选填，优惠码号】
		0,
	)
	// 大小写装换
	data1, _ := common.Marshal(data)
	data2 := make(map[string]interface{})
	json.Unmarshal(data1, &data2)
	common.JSONOld(c, map[string]interface{}{
		"Data": data2,
	}, err)
}

// Micropay 刷脸支付
func (r Robot) Micropay(c *gin.Context) {
	var params struct {
		SalesID       string `json:"SalesID"`
		OutTradeNo    string `json:"OutTradeNo"` // 后缀F2
		TradeNo       string `json:"TradeNo"`    // 原订单号
		PaymentAmount string `json:"PaymentAmount"`
		AuthCode      string `json:"AuthCode"`
		PayType       int    `json:"PayType"`
	}
	err := c.ShouldBindBodyWith(&params, binding.JSON)
	if err != nil {
		response.JSON(c, nil, errorx.New("参数错误", -1))
		return
	}

	db := mysql.NewDB()
	paymentAmount, _ := strconv.ParseFloat(params.PaymentAmount, 64)
	res, err := robot.RobotService{}.Micropay(c.Request.Context(), db, params.SalesID, params.OutTradeNo, params.TradeNo, params.AuthCode, params.PayType, paymentAmount)

	data1, _ := common.Marshal(res)
	data2 := make(map[string]interface{})
	json.Unmarshal(data1, &data2)
	common.JSONOld(c, data2, err)
}

// MicropayInit 刷脸支付初始化
func (r Robot) MicropayInit(c *gin.Context) {
	var params struct {
		SalesID  string      `json:"SalesID"`
		MetaInfo interface{} `json:"MetaInfo"`
	}
	err := c.ShouldBindBodyWith(&params, binding.JSON)
	if err != nil {
		response.JSON(c, nil, errorx.New("参数错误", -1))
		return
	}

	merchantID := c.GetString("merchant_id")
	db := mysql.NewDB()
	data, err := robot.RobotService{}.MicropayInit(c.Request.Context(), db, merchantID, params.SalesID, params.MetaInfo)
	data1, _ := common.Marshal(data)
	data2 := make(map[string]interface{})
	json.Unmarshal(data1, &data2)
	common.JSONOld(c, data2, err)
}

// QueryOrder 查询订单
func (r Robot) QueryOrder(c *gin.Context) {
	var params struct {
		SalesID    string `json:"SalesID"`    // sales_id
		OutTradeNo string `json:"OutTradeNo"` // out_trade_no
	}
	err := c.ShouldBindBodyWith(&params, binding.JSON)
	if err != nil {
		common.JSONOld(c, nil, errorx.New("参数错误", -1))
		return
	}

	data, err := robot.RobotService{}.QueryOrder(c.Request.Context(), params.SalesID, params.OutTradeNo)
	data1, _ := common.Marshal(data)
	data2 := make(map[string]interface{})
	json.Unmarshal(data1, &data2)
	common.JSONOld(c, data2, err)
}

// QueryRCOrder 兑换码订单查询
func (r Robot) QueryRCOrder(c *gin.Context) {
	var params struct {
		SalesID    string `json:"SalesID"`    // sales_id
		OutTradeNo string `json:"OutTradeNo"` // out_trade_no
		Code       string `json:"Code"`       // code
	}
	err := c.ShouldBindBodyWith(&params, binding.JSON)
	if err != nil {
		common.JSONOld(c, nil, errorx.New("参数错误", -1))
		return
	}

	data, err := redemption.RedemptionService{}.QueryRCOrder(c.Request.Context(), params.SalesID, params.OutTradeNo, params.Code)
	data1, _ := common.Marshal(data)
	data2 := make(map[string]interface{})
	json.Unmarshal(data1, &data2)
	common.JSONOld(c, data2, err)
}

// 抽奖订单，出货完成
func (r Robot) CloseLotteryOrder(c *gin.Context) {
	var params struct {
		SalesID           string `json:"SalesID"`
		OutTradeNo        string `json:"OutTradeNo"`
		EndType           string `json:"EndType"` // 出货类型: 0出货失败 1出货成功 2订单结束(自己取消)
		EndRemarks        string `json:"EndRemarks"`
		OrigialOutTradeNo string `json:"OrigialOutTradeNo"`
		ErrorCode         string `json:"ErrorCode"`
		LogMsg            string `json:"LogMsg"`
		PushData          string `json:"PushData"`
		PopUp             int    `json:"PopUp"`
	}
	err := c.ShouldBindBodyWith(&params, binding.JSON)
	if err != nil {
		common.JSONOld(c, nil, errorx.New("参数错误", -1))
		return
	}

	// 执行抽奖订单关闭
	// OutTradeNo 主订单号
	robot.RobotService{}.CloseLotteryOrder(context.Background(), params.SalesID, params.OutTradeNo, params.EndType,
		params.PopUp, params.ErrorCode, params.EndRemarks, params.OrigialOutTradeNo, params.LogMsg, params.PushData,
	)

	common.JSONOld(c, nil, nil)
}

// 出货完成
func (r Robot) CloseOrder(c *gin.Context) {
	var params struct {
		SalesID           string `json:"SalesID"`
		OutTradeNo        string `json:"OutTradeNo"`
		EndType           string `json:"EndType"` // 出货类型: 0出货失败 1出货成功 2订单结束(自己取消)
		EndRemarks        string `json:"EndRemarks"`
		OrigialOutTradeNo string `json:"OrigialOutTradeNo"`
		ErrorCode         string `json:"ErrorCode"`
		LogMsg            string `json:"LogMsg"`
		PushData          string `json:"PushData"`
		PopUp             int    `json:"PopUp"`
	}
	err := c.ShouldBindBodyWith(&params, binding.JSON)
	if err != nil {
		common.JSONOld(c, nil, errorx.New("参数错误", -1))
		return
	}
	if params.OutTradeNo == "" {
		common.JSONOld(c, nil, errorx.New("订单号不能为空", -1))
		return
	}

	logx.Info(context.Background(), "order_trace:"+params.OutTradeNo, logx.Any("type", "close_order"), logx.Any("params", params))
	{
		db := mysql.NewDB()
		// 新增POS: 查询当前机器配置了POS，则直接改为Pos
		PaymentTypeMap := service.RobotPayment{}.GetRobotPayments(context.Background(), db, params.SalesID, 0)
		// 只保留13Pos机器支付方式,其他不需要创单，不然会报错
		// var filterPaymentTypes = make(map[string]int)
		if len(PaymentTypeMap) == 1 {
			for k := range PaymentTypeMap {
				if k == "13" {
					// 把订单写成Pos
					mysql.NewDB().Model(&models.MaOrder{}).
						Where("out_trade_no = ?", params.OutTradeNo).
						UpdateColumn("payment_id", 13)
				}
			}
		}
	}

	// 已经关闭的订单，不再处理
	{
		order := models.MaOrder{}
		rowsAffected := mysql.NewDB().Model(&models.MaOrder{}).
			Where("out_trade_no = ?", params.OutTradeNo).
			Take(&order).RowsAffected
		if rowsAffected > 0 && order.End == 1 {
			common.JSONOld(c, nil, nil)
			return
		}
	}
	// 提前标记end状态，避免程序异常，导致end
	{
		// 如果客户手动结束订单，标记end为2
		// 10分钟内，如果并发了出货操作，则会再次出发关闭订单，end先变为3，如果被程序正常处理，最终会变为1
		// 10分钟后（以避开订单关闭和订单出货的并发），如果订单状态为已支付，自动退款[超时支付]
		// 这个由定时任务处理
		if params.EndType == "2" {
			mysql.NewDB().Model(&models.MaOrder{}).
				Where("out_trade_no = ?", params.OutTradeNo).
				Update("end", 2)
		}
		// 出货状态为0或1,标记end为3，标记订单已经被程序处理
		// 0触发退款，1为正常出货
		// 如果被程序正常处理，end的最终状态为1
		// 这个end状态，定时任务不做检测处理
		if params.EndType == "0" || params.EndType == "1" {
			mysql.NewDB().Model(&models.MaOrder{}).
				Where("out_trade_no = ?", params.OutTradeNo).
				Update("end", 3)
		}
		// 如果关闭订单未被调用，则end状态默认为0,该状态认为安卓异常
		// 如果10分钟后，如果订单状态为已支付状态，自动退款[出货无响应]
		// 这个由定时任务处理
	}

	// 执行订单关闭
	robot.RobotService{}.CloseOrder(
		context.Background(),
		params.SalesID,
		params.OutTradeNo, // 主订单号
		params.EndType,
		params.PopUp,
		params.ErrorCode,
		params.EndRemarks,
		params.OrigialOutTradeNo,
		params.LogMsg,
		params.PushData,
	)

	// 正常出货时
	// 优惠码核销确认
	if params.EndType == "1" {
		coupon.CouponCode{}.ConsumeConfirm(c.Request.Context(), params.OutTradeNo)
	}

	// --- 锦鲤活动返回抽奖地址入口 --
	url, _ := lottery.LotteryService{}.CheckLotteryActivity(
		params.SalesID,
		params.OutTradeNo,
	)
	// url := "http://dev.iybot.com/h5-page/page97/index.html#/pages/lottery-activity/guide?out_trade_no=1&activity_id=1&sales_id=1"
	if url == "" {
		// 1. 返回地址给安卓 2.安卓把当前跳转参与的机器识别码，订单号，活动ID 共计3个参数传给前端,前段拿到后进行注册或者登录，3.用户开始抽奖
		common.JSONOld(c, nil, nil)
	} else {
		data := make(map[string]interface{})
		data["Url"] = url
		common.JSONOld(c, data, nil)
	}

}

// GetSwitch 获取开关
func (r Robot) GetSwitch(c *gin.Context) {
	var params struct {
		SalesID string `json:"sales_id"`
	}
	err := c.ShouldBindBodyWith(&params, binding.JSON)
	if err != nil {
		response.JSON(c, nil, errorx.New("参数错误", -1))
		return
	}
	merchantID := c.GetString("merchant_id")
	data, err := robot.RobotService{}.GetSwitch(c.Request.Context(), merchantID, params.SalesID)
	response.JSON(c, data, err)
}

// SetSwitch 控制开关
func (r Robot) SetSwitch(c *gin.Context) {
	var params struct {
		SalesID string `json:"sales_id"`
		Switch  struct {
			Switch1 string `json:"switch1"`
			Switch2 string `json:"switch2"`
			Switch3 string `json:"switch3"`
			Switch4 string `json:"switch4"`
			Switch5 string `json:"switch5"`
		} `json:"switch"`
	}
	err := c.ShouldBindBodyWith(&params, binding.JSON)
	if err != nil {
		response.JSON(c, nil, errorx.New("参数错误", -1))
		return
	}
	merchantID := c.GetString("merchant_id")
	err = robot.RobotService{}.SetSwitch(c.Request.Context(), merchantID, params.SalesID, params.Switch)
	response.JSON(c, nil, err)
}

func (r Robot) ErrorReport(c *gin.Context) {
	var params struct {
		SalesID    string `json:"SalesID"`    // sales_id
		LogMsg     string `json:"LogMsg"`     // log_msg
		ErrorCode  string `json:"ErrorCode"`  // error_code
		OutTradeNo string `json:"OutTradeNo"` // out_trade_no
	}
	err := c.ShouldBindBodyWith(&params, binding.JSON)
	if err != nil {
		common.JSONOld(c, nil, errorx.New("参数错误", -1))
		return
	}

	err = robot.RobotService{}.ErrorReport(c.Request.Context(), params.SalesID, params.LogMsg, params.ErrorCode, params.OutTradeNo)
	common.JSONOld(c, nil, err)
}

// ErrorReportPallets 货盘检测错误上报
func (r Robot) ErrorReportPallets(c *gin.Context) {
	var params struct {
		SalesID    string `form:"SalesID"`
		OutTradeNo string `form:"OutTradeNo"`
		Log        string `form:"Log"`
		ErrorTimer int    `form:"ErrorTimer"`
		Type       int    `form:"Type"`
		Result     int    `form:"Result"`
	}
	err := c.Bind(&params)
	if err != nil {
		response.JSON(c, err, errorx.New("参数错误", -1))
		return
	}

	// 上传货盘截图
	originaImage, _ := c.FormFile("OriginaImagePath")
	inputImage, _ := c.FormFile("InputImagePath")
	primaryKey, _ := helper.UUID{}.String()

	// 创建目录
	{
		errorPath := config.Config.FileSaveDir + "/sale-admin/Image/Error/"
		_, err = os.Stat(errorPath)
		if err != nil {
			os.MkdirAll(errorPath, os.ModePerm)
		}
	}

	OriginaImagePath := config.Config.FileSaveDir + "/sale-admin/Image/Error/" + primaryKey + originaImage.Filename
	InputImagePath := config.Config.FileSaveDir + "/sale-admin/Image/Error/" + primaryKey + inputImage.Filename
	err = c.SaveUploadedFile(originaImage, OriginaImagePath)
	if err != nil {
		response.JSON(c, err, errorx.New("上传失败", -1))
		return
	}
	err = c.SaveUploadedFile(inputImage, InputImagePath)
	if err != nil {
		response.JSON(c, err, errorx.New("上传失败", -1))
		return
	}

	err = robot.RobotService{}.ErrorReportPallets(
		c.Request.Context(),
		c.GetString("merchant_id"),
		params.SalesID,
		params.Type,
		params.Result,
		params.ErrorTimer,
		params.OutTradeNo,
		params.Log,
		OriginaImagePath,
		InputImagePath,
	)
	response.JSON(c, nil, err)
}

// func (r Robot) MyUploadFile(ctx, info *multipart.FileHeader) (fileName string, err error) {
// 	// 处理上传的文件
// 	file, err := ctx.FormFile("file")
// 	if err != nil {
// 		return "", errorx.New("未获取到上传的文件", -1)
// 	}
// 	primaryKey, err := helper.UUID{}.String()
// 	if err != nil {
// 		return "", errorx.New("新建文件名失败", -1)
// 	}

// 	// 保存上传的文件
// 	newFilename := primaryKey + "-" + file.Filename
// 	err = ctx.SaveUploadedFile(file, path.Join(saveDir, newFilename))
// 	if err != nil {
// 		return "", errorx.New("文件保存失败", -1)
// 	}
// }

// GetAPK 获取最新版本apk
func (r Robot) GetAPK(c *gin.Context) {
	var params struct {
		VersionCode int `json:"version_code"`
	}
	err := c.ShouldBindBodyWith(&params, binding.JSON)
	if err != nil {
		response.JSON(c, nil, errorx.New("参数错误", -1))
		return
	}

	merchantID := c.GetString("merchant_id")
	data, err := robot.RobotService{}.GetAPK(c.Request.Context(), merchantID, params.VersionCode)
	response.JSON(c, data, err)
}

// GetAPK 获取最新版本apk peter test
func (r Robot) GetAPKTest(c *gin.Context) {
	var params struct {
		VersionCode int `json:"version_code"`
	}
	err := c.ShouldBindBodyWith(&params, binding.JSON)
	if err != nil {
		response.JSON(c, nil, errorx.New("参数错误", -1))
		return
	}

	merchantID := c.GetString("merchant_id")
	data, err := robot.RobotService{}.GetAPK(c.Request.Context(), merchantID, params.VersionCode)
	response.JSON(c, data, err)

}

// GetAPK 获取最新版本apk peter test接口
// func (r Robot) GetAPKTest(c *gin.Context) {
// 	var params struct {
// 		VersionCode int `json:"version_code"`
// 	}
// 	err := c.ShouldBindBodyWith(&params, binding.JSON)
// 	if err != nil {
// 		response.JSON(c, nil, errorx.New("参数错误", -1))
// 		return
// 	}

// 	merchantID := c.GetString("merchant_id")
// 	data, err := robot.RobotService{}.GetAPK(c.Request.Context(), merchantID, params.VersionCode)
// 	response.JSON(c, data, err)
// }

func (r Robot) GetRobotType(c *gin.Context) {
	data := []struct {
		Key   int    `json:"key"`
		Label string `json:"label"`
	}{
		{
			Key:   1,
			Label: "自研一代",
		},
		{
			Key:   2,
			Label: "自研二代",
		},
		{
			Key:   3,
			Label: "消杀机器人",
		},
		{
			Key:   4,
			Label: "广告机器人",
		},
		{
			Key:   5,
			Label: "乐Fun机器人",
		},
		{
			Key:   6,
			Label: "SMT",
		},
		{
			Key:   7,
			Label: "E巡机器人",
		},
		{
			Key:   8,
			Label: "飞鼠清洁机",
		},
		{
			Key:   9,
			Label: "陆巡机器人",
		},
		{
			Key:   10,
			Label: "科灵机器人",
		},
		{
			Key:   11,
			Label: "乐Fun机器人二代",
		},
	}
	response.JSON(c, gin.H{
		"DeviceType": data,
	}, nil)
}

func (r Robot) GetErrorPallets(c *gin.Context) {
	var params struct {
		StartTime string `json:"start_time"`
		EndTime   string `json:"end_time"`
		Result    string `json:"result"`
		Type      int    `json:"type"`
		Page      int    `json:"page"`
		Limit     int    `json:"limit"`
	}
	c.ShouldBindBodyWith(&params, binding.JSON)
	db := mysql.NewDB()
	list, count, err := robot.RobotService{}.GetErrorPallets(c.Request.Context(), db, params.StartTime, params.EndTime, params.Result, params.Type, params.Page, params.Limit)
	response.JSON(c, gin.H{
		"list":  list,
		"count": count,
	}, err)
}

// [安卓] 返回所有的支付方式
func (r Robot) AndriodSalesPayment(c *gin.Context) {
	var params struct {
		SalesID string `json:"SalesID"`
	}
	c.ShouldBindBodyWith(&params, binding.JSON)

	data, err := service.RobotPayment{}.GetSalesPayments(
		c.Request.Context(),
		params.SalesID,
	)
	// 转换成首字母大写格式
	data1, _ := common.Marshal(data)
	data2 := map[string]interface{}{}
	json.Unmarshal(data1, &data2)
	common.JSONOld(c, map[string]interface{}{
		"Data": data2,
	}, err)
}

// Background 获取商品首页推荐图
func (r Robot) Background(c *gin.Context) {
	var params struct {
		Position int `json:"position"`
	}
	if c.ShouldBindBodyWith(&params, binding.JSON) != nil {
		common.JSONOld(c, nil, errorx.New("参数错误", -1))
		return
	}

	url, _ := robot.RobotBackground{}.GetBackground(
		c.Request.Context(),
		c.GetHeader("Authorization"),
		params.Position,
	)
	// 转换成首字母大写格式
	data := make(map[string]interface{})
	data["Url"] = url
	common.JSONOld(c, data, nil)
}

func (r Robot) MiniAppPickupQRCode(c *gin.Context) {
	url := config.Config.BaseUrl + "/mini-app-admin/qrcode/pickup?sales_id=" + c.Query("sales_id")
	common.JSONOld(c, map[string]interface{}{
		"Url": url,
	}, nil)
}

// SetPayment 设置机器支付方式
func (r Robot) SetPaymentShowType(c *gin.Context) {
	var params struct {
		SalesID     string `json:"sales_id"`
		PaymentType int    `json:"payment_type"`
	}
	err := c.ShouldBindBodyWith(&params, binding.JSON)
	if err != nil {
		response.JSON(c, nil, errorx.New("参数错误", -1))
		return
	}

	count, err := robot.RobotService{}.SetPaymentShowType(c.Request.Context(), params.SalesID, params.PaymentType)

	if err == nil && count >= 0 {
		response.JSON(c, count, errorx.New("配置成功！", 0))
	} else {
		response.JSON(c, count, errorx.New("配置失败", -1))
	}
}

// SetPayment 设置机器支付方式
func (r Robot) GetPaymentShowType(c *gin.Context) {
	var params struct {
		SalesID string `json:"sales_id"`
	}
	err := c.ShouldBindBodyWith(&params, binding.JSON)
	if err != nil {
		response.JSON(c, nil, errorx.New("参数错误", -1))
		return
	}

	paymentShowType, err := robot.RobotService{}.GetPaymentShowType(c.Request.Context(), params.SalesID)
	if err == nil {
		response.JSON(c, paymentShowType, errorx.New("成功！", 0))
	} else {
		response.JSON(c, -1, errorx.New("失败", -1))
	}
}
